﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using log4net;
using BidFunLib.DAO;
using BidFunLib.Entity;
using NHibernate;

namespace BidFunLib.Services
{
    /// <summary>
    /// 
    /// </summary>
    public class StatsBidUserByBidObjectManager
    {

        private static readonly ILog log = LogManager.GetLogger(typeof(StatsBidUserByBidObjectManager));

        /// <summary>
        /// The dao of this manager
        /// </summary>
        private StatsBidUserByBidObjectDAO dao = new StatsBidUserByBidObjectDAO();

        
        /// <summary>
        /// Singleton instance
        /// </summary>
        private static StatsBidUserByBidObjectManager instance;

        /// <summary>
        /// Retreive singleton of this class
        /// </summary>
        public static StatsBidUserByBidObjectManager Instance
        {
            get
            {
                if (instance == null)
                {
                    instance = new StatsBidUserByBidObjectManager();
                }
                return StatsBidUserByBidObjectManager.instance;
            }
            set
            {
                StatsBidUserByBidObjectManager.instance = value;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        private StatsBidUserByBidObjectManager()
        {
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="idBidUser"></param>
        /// <param name="idBidObject"></param>
        /// <returns></returns>
        public StatsBidUserByBidObject getStatsBidUserByBidObjectByBidUser(BidUser bidUser, BidObject bidObject)
        {
            return dao.getStatsBidUserByBidObjectByBidUser(bidUser.IdBidUser, bidObject.IdBidObject);
        }

        /// <summary>
        /// Update statitics for one user on one sale to the object level (aggregation of all bid on the same object)
        /// Receive all users statistics for a specific bid sale.
        /// 
        /// </summary>
        /// <param name="statsBidSaleList"></param>
        public void calculateStatsBidUserByBidObject(BidSale bidSale, Dictionary<Int32, StatsBidUserByBidSale> mapStatsBidUserByBidSale) 
        {
            if (bidSale != null && mapStatsBidUserByBidSale != null)
            {
                log.Info("calculateStatsBidUserByBidObject");
                StatsBidUserByBidObject statsBidUserByBidObject = null;

                foreach (StatsBidUserByBidSale statsBidUserByBidSale in mapStatsBidUserByBidSale.Values)
                {
                    log.Info("StatsBidUserByBidSale id : " + statsBidUserByBidSale.IdStatsBidUserByBidSale);
                    statsBidUserByBidObject = dao.getStatsBidUserByBidObjectByBidUser(statsBidUserByBidSale.IdBidUser, statsBidUserByBidSale.IdBidObject);

                    if (statsBidUserByBidObject == null)
                    {
                        log.Info("statsBidUserByBidObject must be created (not exist in db).");
                        statsBidUserByBidObject = new StatsBidUserByBidObject();
                        statsBidUserByBidObject.IdStatsBidUserByBidObject = -1;
                        statsBidUserByBidObject.IdBidObject = statsBidUserByBidSale.IdBidObject;
                        statsBidUserByBidObject.IdBidUser = statsBidUserByBidSale.IdBidUser;
                        statsBidUserByBidObject.MinNbBids = 10000000;
                        statsBidUserByBidObject.MinNbBidsManual = 10000000;
                        statsBidUserByBidObject.MinNbBidsByBot = 10000000;
                    }
                    else
                    {
                        log.Info("statsBidUserByBidObject exist in db.");
                    }

                    // concatenation of statistics
                    statsBidUserByBidObject.NbBidSalesParticipation++;

                    statsBidUserByBidObject.NbBidsByBot += statsBidUserByBidSale.NbBidsByBot;
                    if (statsBidUserByBidObject.NbBidSalesParticipation != 0)
                    {
                        statsBidUserByBidObject.MeanNbBidsByBot = statsBidUserByBidObject.NbBidsByBot / statsBidUserByBidObject.NbBidSalesParticipation;
                    }
                    if (statsBidUserByBidObject.NbBidsByBot < statsBidUserByBidObject.MinNbBidsByBot)
                    {
                        statsBidUserByBidObject.MinNbBidsByBot = statsBidUserByBidObject.NbBidsByBot;
                    }
                    if (statsBidUserByBidObject.NbBidsByBot > statsBidUserByBidObject.MaxNbBidsByBot)
                    {
                        statsBidUserByBidObject.MaxNbBidsByBot = statsBidUserByBidObject.NbBidsByBot;
                    }

                    // Nb bids manual statistics
                    statsBidUserByBidObject.NbBidsManual += statsBidUserByBidSale.NbBidsManual;
                    if (statsBidUserByBidObject.NbBidSalesParticipation != 0)
                    {
                        statsBidUserByBidObject.MeanNbBidsManual = statsBidUserByBidObject.NbBidsManual / statsBidUserByBidObject.NbBidSalesParticipation;
                    }
                    if (statsBidUserByBidObject.NbBidsManual < statsBidUserByBidObject.MinNbBidsManual)
                    {
                        statsBidUserByBidObject.MinNbBidsManual = statsBidUserByBidObject.NbBidsManual;
                    }
                    if (statsBidUserByBidObject.NbBidsManual > statsBidUserByBidObject.MaxNbBidsManual)
                    {
                        statsBidUserByBidObject.MaxNbBidsManual = statsBidUserByBidObject.NbBidsManual;
                    }

                    // Nb bids statistics
                    statsBidUserByBidObject.NbBids += statsBidUserByBidSale.NbBids;
                    if (statsBidUserByBidObject.NbBidSalesParticipation != 0)
                    {
                        statsBidUserByBidObject.MeanNbBids = statsBidUserByBidObject.NbBids / statsBidUserByBidObject.NbBidSalesParticipation;
                    }
                    if (statsBidUserByBidObject.NbBids < statsBidUserByBidObject.MinNbBids)
                    {
                        statsBidUserByBidObject.MinNbBids = statsBidUserByBidObject.NbBids;
                    }
                    if (statsBidUserByBidObject.NbBids > statsBidUserByBidObject.MaxNbBids)
                    {
                        statsBidUserByBidObject.MaxNbBids = statsBidUserByBidObject.NbBids;
                    }



                    if (statsBidUserByBidSale.Winner)
                    {
                        statsBidUserByBidObject.NbBidObjectsWon++;
                    }

                    saveOrUpdate(statsBidUserByBidObject);
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="bidLogger"></param>
        /// <returns></returns>
        public StatsBidUserByBidObject saveOrUpdate(StatsBidUserByBidObject statsBidUserByBidObject)
        {
            return dao.saveOrUpdate(statsBidUserByBidObject);
        }

    }
}
